Micron Document
πŸŽ–οΈGitΠ―Ρ€Π°πŸŽ–οΈ

Node / meshtastic / Meshtastic-Android / files / docs / en / developer / adding-a-feature-module.md

Displaying Rendered β€’ View raw β€’ Download

docs/en/developer/adding-a-feature-module.md 89fe2b58d7aa6f0af30af91e2ccf72f365c80bc7 (89fe2b58) Text, 3.59 KB

title: Adding a Feature Module
parent: Developer Guide
nav_order: 3
last_updated: 2026-05-13
aliases:
β€’ new-module
β€’ feature-module
β€’ module-guide

Adding a Feature Module

Step-by-step guide for creating a new KMP feature module in the Meshtastic project.

1. Create the Module Directory

T282828
mkdir -p feature/my-feature/src/Tff7b72{commonMain,commonTest,androidMain,jvmMain,iosMainTff7b72}/kotlin/org/meshtastic/feature/myfeature


2. Create T383838build.gradle.kts

T282828
Te6edf3plugins Tb4b4b4{
Te6edf3aliasTb4b4b4(Te6edf3libsTb4b4b4.Te6edf3pluginsTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3kmpTb4b4b4.Te6edf3featureTb4b4b4)
Tb4b4b4}

Te6edf3kotlin Tb4b4b4{
Te6edf3androidLibrary Tb4b4b4{ Te6edf3withHostTest Tb4b4b4{ Tb4b4b4} Tb4b4b4}

Te6edf3sourceSets Tb4b4b4{
Te6edf3commonMainTb4b4b4.Te6edf3dependencies Tb4b4b4{
Te6edf3implementationTb4b4b4(Te6edf3projectsTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3commonTb4b4b4)
Te6edf3implementationTb4b4b4(Te6edf3projectsTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3navigationTb4b4b4)
Te6edf3implementationTb4b4b4(Te6edf3projectsTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3resourcesTb4b4b4)
Te6edf3implementationTb4b4b4(Te6edf3projectsTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3uiTb4b4b4)
Te6edf3implementationTb4b4b4(Te6edf3projectsTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3diTb4b4b4)
Tb4b4b4}

Te6edf3commonTestTb4b4b4.Te6edf3dependencies Tb4b4b4{
Te6edf3implementationTb4b4b4(Te6edf3libsTb4b4b4.Te6edf3composeTb4b4b4.Te6edf3multiplatformTb4b4b4.Te6edf3uiTb4b4b4.Te6edf3testTb4b4b4)
Tb4b4b4}

Te6edf3jvmTestTb4b4b4.Te6edf3dependencies Tb4b4b4{
Te6edf3implementationTb4b4b4(Te6edf3composeTb4b4b4.Te6edf3desktopTb4b4b4.Te6edf3currentOsTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}


3. Register in T383838settings.gradle.kts

Add your module to the main T383838include() block:

T282828
Te6edf3includeTb4b4b4(
T8b949e// ...existing modules...
Ta5d6ff"Ta5d6ff:feature:my-featureTa5d6ff"Tb4b4b4,
Tb4b4b4)


4. Create the DI Module

T383838src/commonMain/kotlin/org/meshtastic/feature/myfeature/di/FeatureMyFeatureModule.kt:

T282828
Tff7b72package T7ee787org.meshtastic.feature.myfeature.di

Tff7b72import T7ee787org.koin.core.annotation.ComponentScan
Tff7b72import T7ee787org.koin.core.annotation.Module

Tf0883e@Module
Tf0883e@ComponentScanTb4b4b4(Ta5d6ff"Ta5d6fforg.meshtastic.feature.myfeatureTa5d6ff"Tb4b4b4)
Tff7b72class T56d364FeatureMyFeatureModule


5. Register DI in App/Desktop

Add your module to:
β€’ T383838androidApp/src/main/kotlin/org/meshtastic/app/di/AppKoinModule.kt
β€’ T383838desktopApp/src/main/kotlin/org/meshtastic/desktop/di/DesktopKoinModule.kt

6. Add Navigation Routes

In T383838core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/Routes.kt:

T282828
Tf0883e@Serializable
Tff7b72sealed Tff7b72interface T56d364MyFeatureRoute Tb4b4b4: Te6edf3Route Tb4b4b4{
Tf0883e@Serializable Tff7b72data Tff7b72object T56d364MyFeatureGraph Tb4b4b4: Te6edf3MyFeatureRouteTb4b4b4, Te6edf3Graph
Tf0883e@Serializable Tff7b72data Tff7b72object T56d364MyFeatureHome Tb4b4b4: Te6edf3MyFeatureRoute
Tb4b4b4}


7. Create Navigation Entries

T383838src/commonMain/kotlin/org/meshtastic/feature/myfeature/navigation/MyFeatureNavigation.kt:

T282828
Tff7b72package T7ee787org.meshtastic.feature.myfeature.navigation

Tff7b72import T7ee787androidx.navigation3.runtime.EntryProviderScope
Tff7b72import T7ee787org.meshtastic.core.navigation.MyFeatureRoute

Tff7b72fun Td2a8ffEntryProviderScopeTff7b72<Tff7b72*Tff7b72>Tb4b4b4.Te6edf3myFeatureEntriesTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3entryTff7b72<Te6edf3MyFeatureRouteTb4b4b4.Te6edf3MyFeatureHomeTff7b72> Tb4b4b4{
Te6edf3MyFeatureScreenTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}


8. Source Set Guidelines

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Source Set β”‚ Contains β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ T383838commonMain β”‚ Models, ViewModels, shared UI, DI module, navigation β”‚
β”‚ T383838androidMain β”‚ Android-specific implementations (e.g., platform APIs) β”‚
β”‚ T383838jvmMain β”‚ Desktop-specific implementations β”‚
β”‚ T383838iosMain β”‚ iOS-specific implementations β”‚
β”‚ T383838commonTest β”‚ Shared unit tests β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

9. Testing Expectations

Every feature module should have:
β€’ Unit tests in T383838commonTest for business logic
β€’ UI tests using T383838compose-multiplatform-ui-test where appropriate
β€’ No test dependency on other feature modules

10. Checklist

β€’ [ ] Module directory created
β€’ [ ] T383838build.gradle.kts with correct plugins and dependencies
β€’ [ ] Added to T383838settings.gradle.kts
β€’ [ ] DI module created with T383838@ComponentScan
β€’ [ ] DI module registered in app and desktop roots
β€’ [ ] Routes added to T383838Routes.kt
β€’ [ ] Navigation entries registered
β€’ [ ] T383838./gradlew kmpSmokeCompile passes
β€’ [ ] T383838./gradlew :feature:my-feature:allTests passes


Served by rngit 1.4.2 - Generated in 0.38s